/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.escom.healthlc.controller;

import com.escom.healthlc.business.EnfermedadBusiness;
import com.escom.healthlc.business.HistoriaFamiliarBusiness;
import com.escom.healthlc.business.PacienteBusiness;
import com.escom.healthlc.business.ParentescoBusiness;
import com.escom.healthlc.entidad.EnfermedadVO;
import com.escom.healthlc.entidad.HistoriaFamiliarVO;
import com.escom.healthlc.entidad.MedicoVO;
import com.escom.healthlc.entidad.PacienteVO;
import com.escom.healthlc.entidad.ParentescoVO;
import com.escom.healthlc.utils.Constantes;
import com.escom.healthlc.utils.LazySorterHistoria;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ComponentSystemEvent;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author Carlos
 */
@ManagedBean(name = "HistoriaFamiliarController")
@ViewScoped
public class HistoriaFamiliarController {

    private static final Logger logger = LoggerFactory.getLogger(HistoriaFamiliarController.class);

    @ManagedProperty("#{HistoriaFamiliarBusiness}")
    private HistoriaFamiliarBusiness historiaFamiliarBusiness;

    @ManagedProperty("#{PacienteBusiness}")
    private PacienteBusiness pacienteBusiness;

    @ManagedProperty("#{EnfermedadBusiness}")
    private EnfermedadBusiness enfermedadBusiness;

    @ManagedProperty("#{ParentescoBusiness}")
    private ParentescoBusiness parentescoBusiness;

    private List<HistoriaFamiliarVO> historiaFamiliarRetrieve;
    private LazyDataModel<HistoriaFamiliarVO> historiaFamiliarLazyModel;
    private List<ParentescoVO> tiposParentescoCat;
    private List<EnfermedadVO> tiposEnfermedadCat;
    private List<HistoriaFamiliarVO> historiaFamiliarCreate;
    private HistoriaFamiliarVO historiaSelect;
    private String parentescoSelect;
    private String enfermedadesSelect;
    private PacienteVO pacienteCurrent;
    private MedicoVO medicoCurrent;
    private boolean renderPanelAlta;
    private boolean renderPanelConsulta;
    private boolean pageComplete;

    public HistoriaFamiliarController() {
    }

    @PostConstruct
    private void initHistoriaFamiliarController() {
        executeLimpiarObjects(null);
        getPacienteParam();
        getUsuarioSession();
        initTiposEnfermedadCat();
        initTiposParentescoCat();
        getUsuarioSession();
    }

    public void executeCrearHistoriaFamiliar(ActionEvent acEvt) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        FacesMessage facesMessage;
        if (!historiaFamiliarCreate.isEmpty()) {

            for (int i = 0; i < historiaFamiliarCreate.size(); i++) {
                HistoriaFamiliarVO get = historiaFamiliarCreate.get(i);
                EnfermedadVO enfermedad = get.getEnfermedad();
                ParentescoVO parentesco = get.getParentesco();
                logger.debug("Enfermedad {}", enfermedad.toString());
                logger.debug("Parentesco {}", parentesco.toString());

            }
            historiaFamiliarBusiness.createHistoriaFamiliar(historiaFamiliarCreate, pacienteCurrent.getIdPaciente(), medicoCurrent.getIdMedico());
            int estado = historiaFamiliarBusiness.getEstado();
            String messageEstado = historiaFamiliarBusiness.getMessageEstado();
            switch (estado) {
                case Constantes.SIN_ERROR:
                    facesMessage = new FacesMessage(FacesMessage.SEVERITY_INFO, Constantes.MESSAGE_TITLE, messageEstado);
                    facesContext.addMessage(null, facesMessage);
                    break;
                case Constantes.ERROR_BASE_DATOS:
                    facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, Constantes.MESSAGE_TITLE, messageEstado);
                    facesContext.addMessage(null, facesMessage);
                    break;
            }
        } else {
            facesMessage = new FacesMessage(FacesMessage.SEVERITY_WARN, Constantes.MESSAGE_TITLE, "Debe agregar por lo menos una enfermedad y parentesco.");
            facesContext.addMessage(null, facesMessage);
        }
        executeLimpiarObjects(acEvt);
    }

    public void executeConsultaHistoriaFamiliar(ActionEvent acEvt) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        FacesMessage facesMessage;
        historiaFamiliarRetrieve = historiaFamiliarBusiness.retrieveHistoriaByPersona(medicoCurrent, pacienteCurrent);
        int estado = historiaFamiliarBusiness.getEstado();
        String messageEstado = historiaFamiliarBusiness.getMessageEstado();
        logger.debug("messageEstado {}", messageEstado);
        switch (estado) {
            case Constantes.SIN_ERROR:
                facesMessage = new FacesMessage(FacesMessage.SEVERITY_INFO,  Constantes.MESSAGE_TITLE, messageEstado);
                facesContext.addMessage(null, facesMessage);
                break;
            case Constantes.ERROR_BASE_DATOS:
                facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR,  Constantes.MESSAGE_TITLE, messageEstado);
                facesContext.addMessage(null, facesMessage);
                break;
        }
        crearLazyModelHistoria();
        executeChangeToRetrieve();
    }

    public void executeEliminarHistoriaFamiliar(ActionEvent acEvt) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        FacesMessage facesMessage;
        historiaFamiliarBusiness.deleteHistoriaFamiliar(historiaSelect);
        int estado = historiaFamiliarBusiness.getEstado();
        String messageEstado = historiaFamiliarBusiness.getMessageEstado();
        logger.debug("messageEstado {}", messageEstado);
        switch (estado) {
            case Constantes.SIN_ERROR:
                facesMessage = new FacesMessage(FacesMessage.SEVERITY_INFO,  Constantes.MESSAGE_TITLE, messageEstado);
                facesContext.addMessage(null, facesMessage);
                break;
            case Constantes.ERROR_BASE_DATOS:
                facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR,  Constantes.MESSAGE_TITLE, messageEstado);
                facesContext.addMessage(null, facesMessage);
                break;
        }
        crearLazyModelHistoria();
        executeLimpiarObjects(acEvt);
    }

    public void executeAgergarCombinacion(ActionEvent acEvt) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        FacesMessage facesMessage;
        StringTokenizer st;
        HistoriaFamiliarVO historiaFamiliarCombinacion = new HistoriaFamiliarVO();
        st = new StringTokenizer(enfermedadesSelect, ",");
        EnfermedadVO enfermedad = new EnfermedadVO();
        enfermedad.setIdEnfermedad(st.nextToken());
        enfermedad.setEnfermedad(st.nextToken());
        st = new StringTokenizer(parentescoSelect, ",");
        ParentescoVO parentesco = new ParentescoVO();
        parentesco.setIdParentesco(st.nextToken());
        parentesco.setTipoParentesco(st.nextToken());
        historiaFamiliarCombinacion.setEnfermedad(enfermedad);
        historiaFamiliarCombinacion.setParentesco(parentesco);
        boolean existCombinacion = existCombinacion(enfermedad, parentesco);
        if (!existCombinacion) {
            historiaFamiliarCreate.add(historiaFamiliarCombinacion);
            facesMessage = new FacesMessage(FacesMessage.SEVERITY_INFO,  Constantes.MESSAGE_TITLE, "Combinacion agregada");
            facesContext.addMessage(null, facesMessage);
        } else {
            facesMessage = new FacesMessage(FacesMessage.SEVERITY_WARN,  Constantes.MESSAGE_TITLE, "La combinacion ya existe");
            facesContext.addMessage(null, facesMessage);

        }
        enfermedadesSelect = "";
    }

    public boolean existCombinacion(EnfermedadVO enfermedadParameter, ParentescoVO parentescoParameter) {
        for (int i = 0; i < historiaFamiliarCreate.size(); i++) {
            HistoriaFamiliarVO historia = historiaFamiliarCreate.get(i);
            EnfermedadVO enfermedad = historia.getEnfermedad();
            ParentescoVO parentesco = historia.getParentesco();
            if (enfermedad.getIdEnfermedad().equals(enfermedadParameter.getIdEnfermedad())
                    && parentesco.getIdParentesco().equals(parentescoParameter.getIdParentesco())) {
                return true;
            }
        }
        return false;
    }

    public void executeChangeToCreate() {
        if (pacienteCurrent == null) {
            try {
                FacesContext facesContext = FacesContext.getCurrentInstance();
                ExternalContext externalContext = facesContext.getExternalContext();
                String path = ((ServletContext) externalContext.getContext()).getContextPath();
                externalContext.redirect(path + "/view/med-paciente.jsf?select=0");
            } catch (IOException ex) {
                logger.error("Logger Error: {}", ex.getCause().getMessage());
                logger.error("Logger Error: {}", ex.fillInStackTrace().toString());
            }
        }
        renderPanelAlta = true;
        renderPanelConsulta = false;
    }

    public void executeChangeToRetrieve() {
        renderPanelAlta = false;
        renderPanelConsulta = true;
    }

    public void executeLimpiarObjects(ActionEvent acEvt) {
        parentescoSelect = "";
        enfermedadesSelect = "";
        historiaFamiliarCreate = new ArrayList<>();
        historiaFamiliarRetrieve = new ArrayList<>();
        renderPanelAlta = false;
        renderPanelConsulta = false;
    }

    public void renderView(ComponentSystemEvent event) {
        if (!pageComplete) {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            FacesMessage facesMessage;
            facesMessage = new FacesMessage(FacesMessage.SEVERITY_INFO,  Constantes.MESSAGE_TITLE, " TEST");
            facesContext.addMessage(null, facesMessage);
            pageComplete = true;
        }
    }

    public void getUsuarioSession() {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
        HttpSession httpSession = request.getSession(true);
        medicoCurrent = (MedicoVO) httpSession.getAttribute("usuarioActivio");
        logger.debug("medicoCurrent {}", medicoCurrent.toString());
    }

    private void getPacienteParam() {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExternalContext externalContext = facesContext.getExternalContext();
        pacienteCurrent = (PacienteVO) externalContext.getSessionMap().get("idPacienteParam");
    }

    private void crearLazyModelHistoria() {
        historiaFamiliarLazyModel = new LazyDataModel<HistoriaFamiliarVO>() {
            List<HistoriaFamiliarVO> datasource = historiaFamiliarRetrieve;

            @Override
            public HistoriaFamiliarVO getRowData(String rowKey) {
                for (HistoriaFamiliarVO historia : datasource) {
                    if (historia.getIdHistoriaFamiliar().equals(rowKey)) {
                        return historia;
                    }
                }
                return null;
            }

            @Override
            public List<HistoriaFamiliarVO> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters) {
                List<HistoriaFamiliarVO> data = new ArrayList<HistoriaFamiliarVO>();

                //filter  
                for (HistoriaFamiliarVO historia : datasource) {
                    boolean match = true;
                    for (Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
                        try {
                            String filterProperty = it.next();
                            Field field;
                            String filterValue = "";
                            String fieldValue = "";
                            if (filterProperty.contains("parentesco")) {
                                filterValue = filters.get(filterProperty);
                                filterProperty = filterProperty.replace("parentesco.", "");
                                ParentescoVO parentesco = historia.getParentesco();
                                field = parentesco.getClass().getDeclaredField(filterProperty);
                                field.setAccessible(true);
                                fieldValue = String.valueOf(field.get(parentesco));
                            } else if (filterProperty.contains("enfermedad")) {
                                filterValue = filters.get(filterProperty);
                                filterProperty = filterProperty.replace("enfermedad.", "");
                                EnfermedadVO enfermedad = historia.getEnfermedad();
                                field = enfermedad.getClass().getDeclaredField(filterProperty);
                                field.setAccessible(true);
                                fieldValue = String.valueOf(field.get(enfermedad));

                            }
                            if (filterValue == null || fieldValue.contains(filterValue)) {
                                match = true;
                            } else {
                                match = false;
                                break;
                            }
                        } catch (Exception e) {
                            match = false;
                        }
                    }

                    if (match) {
                        data.add(historia);
                    }
                }

//                sort  
                if (sortField != null) {
                    Collections.sort(data, new LazySorterHistoria(sortField, sortOrder));
                }
                if (sortField == null) {
                    sortField = "defaultSortField";
                }
                //rowCount  
                int dataSize = data.size();
                this.setRowCount(dataSize);

                //paginate  
                if (dataSize > pageSize) {
                    try {
                        return data.subList(first, first + pageSize);
                    } catch (IndexOutOfBoundsException e) {
                        return data.subList(first, first + (dataSize % pageSize));
                    }
                } else {
                    return data;
                }
            }

            @Override
            public Object getRowKey(HistoriaFamiliarVO t) {
                return t.getIdHistoriaFamiliar();
            }
        };
    }

    public void setHistoriaFamiliarBusiness(HistoriaFamiliarBusiness historiaFamiliarBusiness) {
        this.historiaFamiliarBusiness = historiaFamiliarBusiness;
    }

    public void setPacienteBusiness(PacienteBusiness pacienteBusiness) {
        this.pacienteBusiness = pacienteBusiness;
    }

    public void setEnfermedadBusiness(EnfermedadBusiness enfermedadBusiness) {
        this.enfermedadBusiness = enfermedadBusiness;
    }

    public void setParentescoBusiness(ParentescoBusiness parentescoBusiness) {
        this.parentescoBusiness = parentescoBusiness;
    }

    private void initTiposEnfermedadCat() {
        tiposEnfermedadCat = enfermedadBusiness.obtenerEnfermedad();

    }

    private void initTiposParentescoCat() {
        tiposParentescoCat = parentescoBusiness.obtenerParentesco();
    }

    public LazyDataModel<HistoriaFamiliarVO> getHistoriaFamiliarLazyModel() {
        return historiaFamiliarLazyModel;
    }

    public void setHistoriaFamiliarLazyModel(LazyDataModel<HistoriaFamiliarVO> historiaFamiliarLazyModel) {
        this.historiaFamiliarLazyModel = historiaFamiliarLazyModel;
    }

    public List<ParentescoVO> getTiposParentescoCat() {
        return tiposParentescoCat;
    }

    public void setTiposParentescoCat(List<ParentescoVO> tiposParentescoCat) {
        this.tiposParentescoCat = tiposParentescoCat;
    }

    public List<EnfermedadVO> getTiposEnfermedadCat() {
        return tiposEnfermedadCat;
    }

    public void setTiposEnfermedadCat(List<EnfermedadVO> tiposEnfermedadCat) {
        this.tiposEnfermedadCat = tiposEnfermedadCat;
    }

    public String getParentescoSelect() {
        return parentescoSelect;
    }

    public void setParentescoSelect(String parentescoSelect) {
        this.parentescoSelect = parentescoSelect;
    }

    public String getEnfermedadesSelect() {
        return enfermedadesSelect;
    }

    public void setEnfermedadesSelect(String enfermedadesSelect) {
        this.enfermedadesSelect = enfermedadesSelect;
    }

    public boolean isRenderPanelAlta() {
        return renderPanelAlta;
    }

    public void setRenderPanelAlta(boolean renderPanelAlta) {
        this.renderPanelAlta = renderPanelAlta;
    }

    public boolean isRenderPanelConsulta() {
        return renderPanelConsulta;
    }

    public void setRenderPanelConsulta(boolean renderPanelConsulta) {
        this.renderPanelConsulta = renderPanelConsulta;
    }

    public List<HistoriaFamiliarVO> getHistoriaFamiliarCreate() {
        return historiaFamiliarCreate;
    }

    public void setHistoriaFamiliarCreate(List<HistoriaFamiliarVO> historiaFamiliarCreate) {
        this.historiaFamiliarCreate = historiaFamiliarCreate;
    }

    public HistoriaFamiliarVO getHistoriaSelect() {
        return historiaSelect;
    }

    public void setHistoriaSelect(HistoriaFamiliarVO historiaSelect) {
        this.historiaSelect = historiaSelect;
    }

}
